﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

/*
 * 与标准INI的区别: 
 *     允许在同一个段中多次出现同一个键
 *     多个相同键的值使用 | 分隔保存在同一个键值中
 */
namespace WatiN.Samples.Console
{
    public class IniField
    {
        private Dictionary<string, string> m_NameValues;
        public IniField()
        {
            m_NameValues = new Dictionary<string, string>();
        }

        public string this[string key]
        {
            get
            {
                string value;
                if (!m_NameValues.TryGetValue(key.ToLower(), out value))
                {
                    value = String.Empty;
                }

                return value;
            }

            set
            {
                m_NameValues[key.ToLower()] = value;
            }
        }
    }

    /// <summary>
    /// 配置文件容器
    /// </summary>
    public class IniConfig
    {
        private Dictionary<string, IniField> m_fields;

        public IniConfig()
        {
            m_fields = new Dictionary<string, IniField>();
        }

        public IniField GetField(string fieldname)
        {
            return GetField(fieldname, false);
        }

        public IniField GetField(string fieldname, bool force)
        {
            IniField field;
            if (!m_fields.TryGetValue(fieldname.ToLower(), out field))
            {
                if (force)
                {
                    field = new IniField();
                    m_fields[fieldname] = field;
                }
                else
                {
                    field = null;
                }
            }
            return field;
        }

        public IniField this[string fieldname]
        {
            get
            {
                return this.GetField(fieldname);
            }
        }
    }

    public static class IniHelper
    {
        public static IniConfig ReadConfig(string filename)
        {
            IniConfig config = new IniConfig();


            StreamReader reader = File.OpenText(filename);
            try
            {
                IniField lastField = null;

                string lastFieldName = String.Empty;

                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();

                    // 删除行首空格
                    line.TrimStart();

                    if (line.StartsWith("#"))
                    {
                        continue;
                    }

                    // 删除行尾注释
                    line = Regex.Replace(line, "#.*$", "");

                    // 删除行尾空格
                    line = line.TrimEnd();


                    Match match;

                    // 判断是否是 [fieldname] 段的分隔
                    match = Regex.Match(line, @"^\[([^\]]+)] *$");
                    if (match.Success)
                    {
                        string curFieldName = match.Result("$1");
                        if (String.Compare(curFieldName, lastFieldName, true) != 0)
                        {
                            lastFieldName = curFieldName;
                            lastField = null; // 清空当前 field 以便后面获得新的
                        }
                    }

                    // 取得 key = value 的值
                    match = Regex.Match(line, @"^([^= ]+) *= *(.*?)$");

                    if (!match.Success)
                    {
                        continue;
                    }

                    if (lastField == null)
                    {
                        lastField = config.GetField(lastFieldName, true);
                    }

                    string key = match.Result("$1"); // 当前行的 key
                    string value = match.Result("$2"); // 当前行的 value


                    if (String.IsNullOrEmpty(lastField[key]))
                    {
                        lastField[key] = value;
                    }
                    else
                    {
                        lastField[key] = String.Format("{0}|{1}", lastField[key], value);
                    }
                }
            }
            finally
            {
                reader.Close();
            }

            return config;

        }
    }
}